home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / VELENG10.ZIP / EVALUATE.C < prev    next >
C/C++ Source or Header  |  1997-07-27  |  50KB  |  2,192 lines

  1. // ****************************************************************************
  2. // *                                                                          *
  3. // *                      Velena Source Code V1.0                             *
  4. // *                   Written by Giuliano Bertoletti                         *
  5. // *       Based on the knowledged approach of Louis Victor Allis             *
  6. // *   Copyright (C) 1996-97 by Giuliano Bertoletti & GBE 32241 Software PR   *
  7. // *                                                                          *
  8. // ****************************************************************************
  9.  
  10. // Portable engine version.
  11. // read the README file for further informations.
  12.  
  13. // ==========================================================================
  14.  
  15.  
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #include <malloc.h>
  20. #include <time.h>
  21. #include <math.h>
  22.  
  23. #include "connect4.h"
  24. #include "con4vals.h"
  25.  
  26. #include "rules.h"
  27. #include "pnsearch.h"
  28. #include "proto.h"
  29.  
  30.  
  31. /* Prototypes */
  32.  
  33. /* That should not be removed in order to get the correct pointer size */
  34.  
  35. struct threat_combo {
  36.                     short cross,even,odd;
  37.                     short gp1,gp2;
  38.                     };
  39.  
  40.  
  41. char **allocate_matrix(struct board *board);
  42.  
  43. char *who[]={"None","White (O)","Black (X)"};
  44. char *eng[]={"Draw","won by White","won by Black"};
  45.  
  46. /* Program */
  47.  
  48. char *rulename[]={"CLAIMEVEN",
  49.                         "BASEINVERSE",
  50.                         "VERTICAL",
  51.                         "AFTEREVEN",
  52.                         "LOWINVERSE",
  53.                         "HIGHINVERSE",
  54.                         "BASECLAIM",
  55.                         "BEFORE",
  56.                         "SPECIALBEFORE"};
  57. /* --------------------------------------------------------------- */
  58.  
  59. void show_square_used(struct board *board)
  60.     {
  61.     short x,y;
  62.  
  63.     for(y=0;y<BOARDY;y++)
  64.         {
  65.         for(x=0;x<BOARDX;x++)
  66.             {
  67.             if(board->sqused[ELM(x,BOARDY-y-1)]) printf("*");
  68.             else printf(".");
  69.             }
  70.         printf("\n");
  71.         }
  72.     }
  73.  
  74. void test_conditions(char **matrix,struct board *board)
  75.     {
  76.     short x,y,z,n1,n2,x1,y1;
  77.  
  78.     printf("Enter rule 1 number : ");
  79.     scanf("%d %d",&x,&y);
  80.  
  81.     printf("\n\r\n\r");
  82.  
  83.     if(x>=0 && x<board->sp && y>=0 && y<board->sp)
  84.         {
  85.         n1=board->solution[x]->solname;
  86.         n2=board->solution[y]->solname;
  87.  
  88.         printf("Rule %d: ",x);
  89.  
  90.         printf("%13s ",rulename[n1-1]);
  91.  
  92.         printf("--> %c%d-%c%d  ",ELX(board->solution[x]->solpoint[0])+65,
  93.                                           ELY(board->solution[x]->solpoint[0])+1,
  94.                                           ELX(board->solution[x]->solpoint[1])+65,
  95.                                           ELY(board->solution[x]->solpoint[1])+1);
  96.  
  97.         for(z=0;z<board->solution[x]->sqinvnumb;z++)
  98.             printf("%c%d ",ELX(board->solution[x]->sqinv[z])+97,
  99.                                  ELY(board->solution[x]->sqinv[z])+1);
  100.  
  101.         printf("\n\r");
  102.  
  103.         printf("Rule %d: ",y);
  104.  
  105.         printf("%13s ",rulename[n2-1]);
  106.  
  107.         printf("--> %c%d-%c%d  ",ELX(board->solution[y]->solpoint[0])+65,
  108.                                           ELY(board->solution[y]->solpoint[0])+1,
  109.                                           ELX(board->solution[y]->solpoint[1])+65,
  110.                                           ELY(board->solution[y]->solpoint[1])+1);
  111.  
  112.         for(z=0;z<board->solution[y]->sqinvnumb;z++)
  113.             printf("%c%d ",ELX(board->solution[y]->sqinv[z])+97,
  114.                                  ELY(board->solution[y]->sqinv[z])+1);
  115.  
  116.         printf("\n\r");
  117.         printf("\n\r");
  118.  
  119.         x1=x;
  120.         y1=y;
  121.  
  122.         if(y1>x1)
  123.             {
  124.             x1=y;
  125.             y1=x;
  126.             }
  127.  
  128.         if(matrix[x1][y1])
  129.             {
  130.             printf("They seem to be compatible :-)))\n\r\n\r");
  131.             }
  132.         else
  133.             {
  134.             printf("They don't seem to be compatible :-(((\n\r\n\r");
  135.             }
  136.  
  137.         }
  138.     else
  139.         {
  140.         printf("Rules %d,%d don't exist!\n\r\n\r");
  141.         }
  142.  
  143.     }
  144.  
  145. void update_log(struct board *board)
  146.     {
  147.     time_t t;
  148.     short x;
  149.     FILE *h1;
  150.  
  151.     h1=fopen(LOGFILE,"a+");
  152.     if(!h1) fatal_error("Cannot open logfile");
  153.  
  154.     time(&t);
  155.     fprintf(h1,"%s",ctime(&t));
  156.     fprintf(h1,"Game played: ");
  157.  
  158.     for(x=0;x<board->filled;x++)
  159.         putc(board->moves[x]+0x31,h1);
  160.  
  161.     fprintf(h1," (%d moves)",board->filled);
  162.     fprintf(h1," %s\n",eng[board->lastwin]);
  163.  
  164.     fprintf(h1,"\n");
  165.     fclose(h1);
  166.     }
  167.  
  168. void dump_file_threat(struct board *board,short anythreat)
  169.     {
  170.     short px1,px2,py1,py2;
  171.     FILE *h1;
  172.  
  173.     h1=fopen(LOGFILE,"a+");
  174.     if(!h1) fatal_error("Cannot open logfile");
  175.  
  176.     px1=board->xplace[anythreat][0];
  177.     py1=board->yplace[anythreat][0];
  178.  
  179.     px2=board->xplace[anythreat][3];
  180.     py2=board->yplace[anythreat][3];
  181.  
  182.     fprintf(h1,"Group taken as odd threat for white is %c%d-%c%d\n\n",px1+97,py1+1,px2+97,py2+1);
  183.     fclose(h1);
  184.     }
  185.  
  186. void dump_file_board(struct board *board)
  187.     {
  188.     short x,y,z;
  189.     FILE *h1;
  190.  
  191.     h1=fopen(LOGFILE,"a+");
  192.     if(!h1) fatal_error("Cannot write to logfile");
  193.  
  194.     fprintf(h1,"------------------------------------------------------------------------\n\n");
  195.     fprintf(h1,"Current board status: ");
  196.  
  197.     for(x=0;x<board->filled;x++)
  198.         fputc(board->moves[x]+0x31,h1);
  199.  
  200.     fprintf(h1,"\n\n");
  201.  
  202.     for(y=BOARDY-1;y>=0;y--)
  203.         {
  204.         for(x=0;x<BOARDX;x++)
  205.             {
  206.             z=board->square[ELM(x,y)];
  207.             if(z==EMPTY) fprintf(h1," .");
  208.             else if(z==WHITE) fprintf(h1," O");
  209.             else fprintf(h1," X");
  210.             }
  211.         fprintf(h1,"\n\n");
  212.         }
  213.  
  214.     fprintf(h1,"%s is to move\n",who[board->turn]);
  215.  
  216.     fclose(h1);
  217.     }
  218.  
  219.  
  220. /***************************************************************************/
  221.  
  222. short odd_threat(struct board *board,short x)
  223.     {
  224.     short y,empty=0,fill=0,emp[TILES],px,py;
  225.  
  226.     for(y=0;y<TILES;y++)
  227.         {
  228.         if(*board->groups[x][y]==EMPTY)
  229.             {
  230.             px=board->xplace[x][y];
  231.             py=board->yplace[x][y];
  232.             emp[empty++]=ELM(px,py);
  233.             }
  234.         else if (*board->groups[x][y]==WHITE) fill++;
  235.         }
  236.  
  237.     if(empty==1 && fill==3 && (py&1)==0 && board->stack[px]<py) return emp[0];
  238.     return -1;
  239.     }
  240.  
  241. void wipe_above(struct board *board,short sq)
  242.     {
  243.     short x,y,z;
  244.  
  245.     x=ELX(sq);
  246.     y=ELY(sq);
  247.  
  248.     for(z=y;z<BOARDY;z++)
  249.         board->wipesq[ELM(x,z)]=1;
  250.     }
  251.  
  252. void wipe_odd(struct board *board,short sq)
  253.     {
  254.     short x,y,z,ye;
  255.  
  256.     x=ELX(sq);
  257.     y=(board->stack[x]&0x0e)+2;
  258.     ye=ELY(sq);
  259.  
  260.     for(z=y;z<=ye;z+=2)
  261.         board->wipesq[ELM(x,z)]=1;
  262.     }
  263.  
  264. short wiped_group(struct board *board,short group)
  265.     {
  266.     short x,px,py;
  267.  
  268.     for(x=0;x<TILES;x++)
  269.         {
  270.         px=board->xplace[group][x];
  271.         py=board->yplace[group][x];
  272.  
  273.         if(board->wipesq[ELM(px,py)]) return YES;
  274.         }
  275.  
  276.     return NO;
  277.     }
  278.  
  279. short check_threat(struct board *board,short px,short i,short side)
  280.     {
  281.     short x,y,p1,p2,fx,fy,j;
  282.  
  283.     for(y=0;y<board->solvable_groups->sqpnt[ELM(px,i)];y++)
  284.         {
  285.         j=board->solvable_groups->square[ELM(px,i)][y];
  286.  
  287.         if(board->xplace[j][0]==board->xplace[j][3]) continue;
  288.  
  289.         p1=0;
  290.         p2=0;
  291.  
  292.         for(x=0;x<TILES;x++)
  293.             {
  294.             fx=board->xplace[j][x];
  295.             fy=board->yplace[j][x];
  296.  
  297.             if(board->square[ELM(fx,fy)]==side) p1++;
  298.             else if (board->square[ELM(fx,fy)]==EMPTY) p2++;
  299.             }
  300.  
  301.         if(p1+p2==TILES) return YES;
  302.         }
  303.  
  304.     return NO;
  305.     }
  306.  
  307. short check_men(struct board *board,short group,short side)
  308.     {
  309.     short x,y,p1=0,p2=0,fx,fy;
  310.  
  311.     for(x=0;x<TILES;x++)
  312.         {
  313.         fx=board->xplace[group][x];
  314.         fy=board->yplace[group][x];
  315.  
  316.         if(board->square[ELM(fx,fy)]==side) p1++;
  317.         else if (board->square[ELM(fx,fy)]==EMPTY) p2++;
  318.         }
  319.  
  320.     return ((p1+p2==4)?p1:-1);
  321.     }
  322.  
  323.  
  324. short check_even_below(struct board *board,short square,short side)
  325.     {
  326.     short px,py,i;
  327.  
  328.     px=ELX(square);
  329.     py=ELY(square);
  330.  
  331.     for(i=1;i<py;i+=2)
  332.         if(board->square[ELM(px,i)]==EMPTY && check_threat(board,px,i,side))
  333.             return YES;
  334.  
  335.     return NO;
  336.     }
  337.  
  338. short count_odd_threats(struct board *board,short *threats)
  339.     {
  340.     short x,y,oddpnt=0;
  341.  
  342.     for(x=0;x<GROUPS;x++)
  343.         {
  344.         y=odd_threat(board,x);
  345.         if(y!=-1) threats[oddpnt++]=y;
  346.         }
  347.  
  348.     return oddpnt;
  349.     }
  350.  
  351. /* --------------------------------------------------------------- */
  352.  
  353. void both_groups(struct board *board,short q1,short q2)
  354.     {
  355.     short x,y,p1,p2,g1,g2;
  356.  
  357.     p1=board->solvable_groups->sqpnt[q1];
  358.     p2=board->solvable_groups->sqpnt[q2];
  359.  
  360.     for(x=0;x<p1;x++)
  361.         for(y=0;y<p2;y++)
  362.             {
  363.             g1=board->solvable_groups->square[q1][x];
  364.             g2=board->solvable_groups->square[q2][y];
  365.             if(g1==g2 && board->intgp.tgroups[g1])
  366.                 board->solution[board->sp]->solgroups[board->solution[board->sp]->solgroupsnumb++]=g1;
  367.             }
  368.     }
  369.  
  370. short recurse_groups(struct board *board,short cols,short *cl,short gp)
  371.     {
  372.     short p,i,g1,g2;
  373.  
  374.     p=board->solvable_groups->sqpnt[cl[0]];
  375.  
  376.     for(i=0;i<p;i++)
  377.         {
  378.         g1=board->solvable_groups->square[cl[0]][i];
  379.         if(cols==1 && g1==gp) return YES;
  380.         else if(g1==gp && recurse_groups(board,cols-1,&cl[1],g1)) return YES;
  381.         }
  382.  
  383.     return NO;
  384.     }
  385.  
  386. void both_many_groups(struct board *board,short cols,short *cl)
  387.     {
  388.     short p,i,g1;
  389.  
  390.     if(cols==0) return;
  391.  
  392.     p=board->solvable_groups->sqpnt[cl[0]];
  393.  
  394.     for(i=0;i<p;i++)
  395.         {
  396.         g1=board->solvable_groups->square[cl[0]][i];
  397.         if(!board->intgp.tgroups[g1]) continue;
  398.  
  399.         if(cols==1 || recurse_groups(board,cols-1,&cl[1],g1))
  400.             board->solution[board->sp]->solgroups[board->solution[board->sp]->solgroupsnumb++]=g1;
  401.         }
  402.     }
  403.  
  404. void solve_columns(struct board *board,short cl,short *cols)
  405.     {
  406.     short i,j,k,t,answer;
  407.     short px,py,tx,ty;
  408.  
  409.     for(i=0;i<GROUPS;i++)
  410.         {
  411.         if(board->intgp.tgroups[i]!=YES) continue;
  412.  
  413.         answer=YES;
  414.  
  415.         for(j=0;j<cl && answer;j++)
  416.             {
  417.             answer=NO;
  418.  
  419.             px=ELX(cols[j]);
  420.             py=ELY(cols[j]);
  421.  
  422.             for(k=0;k<TILES && !answer;k++)
  423.                 {
  424.                 if(*board->groups[i][k]==EMPTY &&
  425.                   px==board->xplace[i][k] &&
  426.                   py<=board->yplace[i][k]) answer=YES;
  427.                 }
  428.             }
  429.  
  430.         if(j==cl && answer)
  431.             {
  432.             if(board->solution[board->sp]->solgroupsnumb==0)
  433.                 {
  434.                 board->solution[board->sp]->sqinvnumb=2*cl;
  435.                 for(t=0;t<cl;t++)
  436.                     {
  437.                     tx=ELX(cols[t]);
  438.                     ty=ELY(cols[t]);
  439.  
  440.                     board->solution[board->sp]->sqinv[t   ]=ELM(tx,ty-1);
  441.                     board->solution[board->sp]->sqinv[t+cl]=ELM(tx,ty);
  442.                     }
  443.                 }
  444.             board->solution[board->sp]->solgroups[board->solution[board->sp]->solgroupsnumb++]=i;
  445.             }
  446.         }
  447.     }
  448.  
  449. void check_claim(struct board *board,short *cl)
  450.     {
  451.     short x,y,z;
  452.     short px,py;
  453.  
  454.     px=ELX(cl[1]);
  455.     py=ELY(cl[1])+1;
  456.  
  457.     if(py<BOARDY && (py&1)==1)
  458.         {
  459.         board->solution[board->sp]->solgroupsnumb=0;
  460.         board->solution[board->sp]->solname=BASECLAIM;
  461.         board->solution[board->sp]->sqinv[0]=cl[0];
  462.         board->solution[board->sp]->sqinv[1]=cl[1];
  463.         board->solution[board->sp]->sqinv[2]=cl[2];
  464.         board->solution[board->sp]->sqinv[3]=ELM(px,py);
  465.         board->solution[board->sp]->sqinvnumb=4;
  466.  
  467.         board->solution[board->sp]->solpoint[0]=cl[0];
  468.         board->solution[board->sp]->solpoint[1]=ELM(px,py);
  469.         both_groups(board,cl[0],ELM(px,py));
  470.         board->instances[BASECLAIM]++;
  471.         if(board->solution[board->sp]->solgroupsnumb>0)
  472.             {
  473.             both_groups(board,cl[1],cl[2]);
  474.             board->sp++;
  475.             }
  476.         board->solution[board->sp]->solgroupsnumb=0;
  477.         board->solution[board->sp]->solname=BASECLAIM;
  478.         board->solution[board->sp]->sqinv[0]=cl[0];
  479.         board->solution[board->sp]->sqinv[1]=cl[1];
  480.         board->solution[board->sp]->sqinv[2]=cl[2];
  481.         board->solution[board->sp]->sqinv[3]=ELM(px,py);
  482.         board->solution[board->sp]->sqinvnumb=4;
  483.         board->solution[board->sp]->solpoint[0]=ELM(px,py);
  484.         board->solution[board->sp]->solpoint[1]=cl[2];
  485.         both_groups(board,ELM(px,py),cl[2]);
  486.         board->instances[BASECLAIM]++;
  487.         if(board->solution[board->sp]->solgroupsnumb>0)
  488.             {
  489.             both_groups(board,cl[0],cl[1]);
  490.             board->sp++;
  491.             }
  492.         }
  493.     }
  494.  
  495. void generate_all_other_before_instances(struct board *board,short cols,short *cl,short j)
  496.     {
  497.     short cnt=0,step,pn[4];
  498.     short gc[4][3],sl[4][2];
  499.     short x,y,px,py,flag,px1,px2,py1,py2;
  500.  
  501.     step=(128>>cols);
  502.  
  503.     for(x=0;x<cols;x++)
  504.         {
  505.         px=ELX(cl[x]);
  506.         py=ELY(cl[x]);
  507.  
  508.         gc[x][2]=cl[x];
  509.         gc[x][1]=ELM(px,py-1);
  510.         if(board->stack[px]<=py-2) gc[x][0]=ELM(px,py-2);
  511.         else gc[x][0]=-1;
  512.         }
  513.  
  514.     while(cnt<128)
  515.         {
  516.         pn[0]=(cnt>>6)&1;
  517.         pn[1]=(cnt>>5)&1;
  518.         pn[2]=(cnt>>4)&1;
  519.         pn[3]=(cnt>>3)&1;
  520.  
  521.         for(x=0;x<cols;x++)
  522.             {
  523.             sl[x][1]=gc[x][1+pn[x]];
  524.             sl[x][0]=gc[x][0+pn[x]];
  525.             }
  526.  
  527.         flag=YES;
  528.         for(x=0;x<cols && flag;x++)
  529.             if(sl[x][0]==-1) flag=FALSE;
  530.  
  531.         for(y=0;y<2 && flag;y++)
  532.             for(x=0;x<cols && flag;x++)
  533.                 if(board->sqused[sl[x][y]]==NO) flag=FALSE;
  534.  
  535.         if(flag)
  536.             {
  537.             board->solution[board->sp]->solgroupsnumb=0;
  538.             board->solution[board->sp]->solname=BEFORE;
  539.             board->solution[board->sp]->solpoint[0]=ELM(board->xplace[j][0],board->yplace[j][0]);
  540.             board->solution[board->sp]->solpoint[1]=ELM(board->xplace[j][3],board->yplace[j][3]);
  541.  
  542.             board->solution[board->sp]->sqinvnumb=2*cols;
  543.             for(x=0;x<2*cols;x++)
  544.                 board->solution[board->sp]->sqinv[x]=sl[x>>1][x&1];
  545.  
  546.             for(x=0;x<cols;x++)
  547.                 {
  548.                 py2=ELY(sl[x][1]);
  549.  
  550.                 if((py2&1)==1) both_many_groups(board,1,&sl[x][1]);
  551.                 else both_groups(board,sl[x][0],sl[x][1]);
  552.                 }
  553.  
  554.             both_many_groups(board,cols,cl);
  555.             board->instances[BEFORE]++;
  556.  
  557.             if(board->solution[board->sp]->solgroupsnumb>0) board->sp++;
  558.             }
  559.  
  560.         cnt+=step;
  561.         }
  562.     }
  563.  
  564. /* ******************************************************************** */
  565.  
  566.  
  567. /* ******************************************************************** */
  568.  
  569. void check_double_threat(struct board *board,short x,short y,
  570.                                  struct threat_combo *tch,short *pnt)
  571.     {
  572.     short j,k,wx,pq,w1,w2,px,py,g1,g2,jg,kg;
  573.  
  574.     pq=ELM(x,y);
  575.  
  576.     for(j=0;j<board->solvable_groups->sqpnt[pq]-1;j++)
  577.         for(k=j+1;k<board->solvable_groups->sqpnt[pq];k++)
  578.             {
  579.          jg=board->solvable_groups->square[pq][j];
  580.             kg=board->solvable_groups->square[pq][k];
  581.  
  582.             w1=check_men(board,jg,WHITE);
  583.             w2=check_men(board,kg,WHITE);
  584.  
  585.             if(w1!=2 || w2!=2) continue;
  586.  
  587.             for(wx=0;wx<TILES;wx++)
  588.                 {
  589.                 px=board->xplace[jg][wx];
  590.                 py=board->yplace[jg][wx];
  591.  
  592.                 if(*board->groups[jg][wx]==EMPTY && (px!=x || py!=y))
  593.                     g1=ELM(px,py);
  594.                 }
  595.  
  596.             for(wx=0;wx<TILES;wx++)
  597.                 {
  598.                 px=board->xplace[kg][wx];
  599.                 py=board->yplace[kg][wx];
  600.  
  601.                 if(*board->groups[kg][wx]==EMPTY && (px!=x || py!=y))
  602.                     g2=ELM(px,py);
  603.                 }
  604.  
  605.             if(ELX(g1)==ELX(g2) && abs(ELY(g1)-ELY(g2))==1)
  606.                 {
  607.                 tch[*pnt].cross=pq;
  608.  
  609.                 if((ELY(g1)&1)==1)
  610.                     {
  611.                     tch[*pnt].even=g1;
  612.                     tch[*pnt].odd =g2;
  613.                     }
  614.                 else
  615.                     {
  616.                     tch[*pnt].odd =g1;
  617.                     tch[*pnt].even=g2;
  618.                     }
  619.  
  620.                 tch[*pnt].gp1=jg;
  621.                 tch[*pnt].gp2=kg;
  622.  
  623.                 (*pnt)++;
  624.                 }
  625.             }
  626.     }
  627.  
  628. short threat_combo(struct board *board,struct threat_combo *tc)
  629.     {
  630.     short x,y,z=0;
  631.  
  632.     /* The common square must be odd */
  633.     for(y=2;y<BOARDY;y+=2)
  634.         for(x=0;x<BOARDX;x++)
  635.             if(board->stack[x]<y) check_double_threat(board,x,y,tc,&z);
  636.  
  637.     return z;
  638.     }
  639.  
  640. /* --------------------------------------------------------------- */
  641.  
  642. void wipe_many_groups(struct board *board,short cols,short *cl)
  643.     {
  644.     short p,i,g1;
  645.  
  646.     if(cols==0) return;
  647.  
  648.     p=board->solvable_groups->sqpnt[cl[0]];
  649.  
  650.     for(i=0;i<p;i++)
  651.         {
  652.         g1=board->solvable_groups->square[cl[0]][i];
  653.         if(!board->usablegroup[g1]) continue;
  654.  
  655.         if(cols==1 || recurse_groups(board,cols-1,&cl[1],g1))
  656.             board->usablegroup[g1]=NO;
  657.         }
  658.     }
  659.  
  660.  
  661.  
  662. void handle_even_above_odd(struct board *board,struct threat_combo *tc)
  663.     {
  664.     short x,y,y1,y2,px,py,qx,qy,sx,sy;
  665.     short cl[2];
  666.  
  667.     /* Rule one */
  668.     wipe_odd(board,tc->cross);
  669.  
  670.     /* Rule two */
  671.     px=ELX(tc->cross);
  672.     py=ELY(tc->cross)+1;
  673.  
  674.     qx=ELX(tc->odd);
  675.     qy=ELY(tc->odd)+1;
  676.  
  677.     for(y1=qy;y1<BOARDY;y1++)
  678.         for(y2=py;y2<BOARDY;y2++)
  679.             {
  680.             cl[0]=ELM(qx,y1);
  681.             cl[1]=ELM(px,y2);
  682.  
  683.             wipe_many_groups(board,2,cl);
  684.             }
  685.  
  686.     /* Rule three */
  687.  
  688.     cl[0]=tc->odd;
  689.     cl[1]=ELM(ELX(tc->cross),ELY(tc->cross)+1);
  690.     wipe_many_groups(board,2,cl);
  691.  
  692.  
  693.     /* Rule four */
  694.  
  695.     if(board->stack[qx]==ELY(tc->odd))
  696.         {
  697.         sx=px;
  698.         sy=py+1;
  699.  
  700.         wipe_above(board,ELM(sx,sy));
  701.         }
  702.  
  703.     /* Rule five */
  704.  
  705.     if((board->stack[px]&1)==0 && board->stack[qx]<(qy-1))
  706.         {
  707.         cl[0]=ELM(px,board->stack[px]);
  708.         cl[1]=ELM(qx,board->stack[qx]);
  709.  
  710.         wipe_many_groups(board,2,cl);
  711.         }
  712.  
  713.     /* Rule six */
  714.  
  715.     qx=ELX(tc->odd);
  716.     qy=board->stack[qx];
  717.  
  718.     for(y=qy;y<BOARDY-1;y++)
  719.         {
  720.         cl[0]=ELM(qx,y);
  721.         cl[1]=ELM(qx,y+1);
  722.  
  723.         wipe_many_groups(board,2,cl);
  724.         }
  725.     }
  726.  
  727.  
  728. void handle_odd_above_even(struct board *board,struct threat_combo *tc)
  729.     {
  730.     short x,y,y1,y2,px,py,qx,qy;
  731.     short cl[2];
  732.  
  733.     /* Rule one */
  734.     wipe_odd(board,tc->cross);
  735.  
  736.     /* Rule two */
  737.     px=ELX(tc->cross);
  738.     py=ELY(tc->cross)+1;
  739.  
  740.     qx=ELX(tc->even);
  741.     qy=ELY(tc->even)+1;
  742.  
  743.     for(y1=qy;y1<BOARDY;y1++)
  744.         for(y2=py;y2<BOARDY;y2++)
  745.             {
  746.             cl[0]=ELM(qx,y1);
  747.             cl[1]=ELM(px,y2);
  748.  
  749.             wipe_many_groups(board,2,cl);
  750.             }
  751.  
  752.     /* Rule three */
  753.  
  754.     if((board->stack[px]&1)==0 && board->stack[qx]<(qy-1))
  755.         {
  756.         cl[0]=ELM(px,board->stack[px]);
  757.         cl[1]=ELM(qx,board->stack[qx]);
  758.  
  759.         wipe_many_groups(board,2,cl);
  760.         }
  761.  
  762.     /* Rule four */
  763.  
  764.     qx=ELX(tc->odd);
  765.     qy=board->stack[qx];
  766.  
  767.     for(y=qy;y<BOARDY-1;y++)
  768.         {
  769.         cl[0]=ELM(qx,y);
  770.         cl[1]=ELM(qx,y+1);
  771.  
  772.         wipe_many_groups(board,2,cl);
  773.         }
  774.     }
  775.  
  776.  
  777. /* --------------------------------------------------------------- */
  778.  
  779.  
  780.  
  781. /* --------------------------------------------------------------- */
  782.  
  783. void claimeven(struct board *board)
  784.     {
  785.     short x1,y1,q1,q2;
  786.     short sln,*grp,j,k;
  787.  
  788.     for(y1=1;y1<BOARDY;y1+=2)
  789.         for(x1=0;x1<BOARDX;x1++)
  790.             {
  791.             if(!board->sqused[ELM(x1,y1)]) continue;
  792.  
  793.             board->solution[board->sp]->solgroupsnumb=0;
  794.  
  795.             q1=ELM(x1,y1);
  796.             q2=ELM(x1,y1-1);
  797.  
  798.             if(board->square[q1]==EMPTY &&
  799.                 board->square[q2]==EMPTY && board->sqused[q2])
  800.                     {
  801.                     sln=board->solvable_groups->sqpnt[q1];
  802.                     grp=board->solvable_groups->square[q1];
  803.  
  804.                     for(j=0;j<sln;j++)
  805.                         if(board->intgp.tgroups[grp[j]]==YES)
  806.                             {
  807.                             if(board->solution[board->sp]->solgroupsnumb==0)
  808.                                 {
  809.                                 board->solution[board->sp]->solname=CLAIMEVEN;
  810.                                 board->solution[board->sp]->solpoint[0]=q1;
  811.                                 board->solution[board->sp]->solpoint[1]=q2;
  812.                                 board->solution[board->sp]->sqinv[0]=q1;
  813.                                 board->solution[board->sp]->sqinv[1]=q2;
  814.                                 board->solution[board->sp]->sqinvnumb=2;
  815.                         board->instances[CLAIMEVEN]++;
  816.                                 }
  817.                             board->solution[board->sp]->solgroups[board->solution[board->sp]->solgroupsnumb++]=grp[j];
  818.                             }
  819.                     }
  820.  
  821.             if(board->solution[board->sp]->solgroupsnumb>0) board->sp++;
  822.             }
  823.     }
  824.  
  825.  
  826. void baseinverse(struct board *board)
  827.     {
  828.     short x1,y1,q1,q2,px,py,wx,wy;
  829.     short sln,*grp,j,k,x,y;
  830.     char  set[64];
  831.  
  832.     for(y1=0;y1<BOARDY;y1++)
  833.         for(x1=0;x1<BOARDX;x1++)
  834.             {
  835.             q1=ELM(x1,y1);
  836.             if(!board->sqused[q1]) continue;
  837.  
  838.             if(board->stack[x1]==y1)
  839.                 {
  840.                 memset(set,YES,64);
  841.  
  842.                 sln=board->solvable_groups->sqpnt[q1];
  843.                 grp=board->solvable_groups->square[q1];
  844.  
  845.                 for(j=0;j<sln;j++)
  846.                     {
  847.                     if(board->intgp.tgroups[grp[j]]==YES)
  848.                         {
  849.                         for(x=0;x<TILES;x++)
  850.                             {
  851.                             wx=board->xplace[grp[j]][x];
  852.                             wy=board->yplace[grp[j]][x];
  853.  
  854.                             if(x1<wx && board->stack[wx]==wy &&
  855.                                 set[ELM(wx,wy)] && board->sqused[ELM(wx,wy)])
  856.                                 {
  857.                                 set[ELM(wx,wy)]=NO;
  858.                                 board->solution[board->sp]->solgroupsnumb=0;
  859.                                 board->solution[board->sp]->solname=BASEINVERSE;
  860.                                 board->solution[board->sp]->solpoint[0]=q1;
  861.                                 board->solution[board->sp]->solpoint[1]=ELM(wx,wy);
  862.                                 board->solution[board->sp]->sqinv[0]=q1;
  863.                                 board->solution[board->sp]->sqinv[1]=ELM(wx,wy);
  864.                                 board->solution[board->sp]->sqinvnumb=2;
  865.                                 both_groups(board,q1,ELM(wx,wy));
  866.                                 board->instances[BASEINVERSE]++;
  867.                                 if(board->solution[board->sp]->solgroupsnumb>0)
  868.                                     board->sp++;
  869.                                 }
  870.                             }
  871.                         }
  872.                     }
  873.                 }
  874.             }
  875.     }
  876.  
  877.  
  878. void vertical(struct board *board)
  879.     {
  880.     short x1,y1,q1,wy;
  881.     short sln,*grp,j,x;
  882.     char set[64];
  883.  
  884.     for(y1=0;y1<BOARDY;y1++)
  885.         for(x1=0;x1<BOARDX;x1++)
  886.             {
  887.             q1=ELM(x1,y1);
  888.             if(!board->sqused[q1]) continue;
  889.  
  890.             if(board->square[q1]==EMPTY)
  891.                 {
  892.                 memset(set,YES,64);
  893.  
  894.                 sln=board->solvable_groups->sqpnt[q1];
  895.                 grp=board->solvable_groups->square[q1];
  896.  
  897.                 for(j=0;j<sln;j++)
  898.                     {
  899.                     if(board->intgp.tgroups[grp[j]]==YES &&
  900.                         board->xplace[grp[j]][0]==board->xplace[grp[j]][3])
  901.                             {
  902.                             for(x=0;x<TILES;x++)
  903.                                 {
  904.                                 wy=board->yplace[grp[j]][x];
  905.  
  906.                                 if(wy>0 && (wy&1)==0 && y1==wy-1 &&
  907.                                     set[ELM(x1,wy)] && board->sqused[ELM(x1,wy)])
  908.                                     {
  909.                                     set[ELM(x1,wy)]=NO;
  910.                                     board->solution[board->sp]->solgroupsnumb=0;
  911.                                     board->solution[board->sp]->solname=VERTICAL;
  912.                                     board->solution[board->sp]->solpoint[0]=q1;
  913.                                     board->solution[board->sp]->solpoint[1]=ELM(x1,wy);
  914.                                     board->solution[board->sp]->sqinv[0]=q1;
  915.                                     board->solution[board->sp]->sqinv[1]=ELM(x1,wy);
  916.                                     board->solution[board->sp]->sqinvnumb=2;
  917.                                     both_groups(board,q1,ELM(x1,wy));
  918.                                     board->instances[VERTICAL]++;
  919.                                     if(board->solution[board->sp]->solgroupsnumb>0) board->sp++;
  920.                                     }
  921.                                 }
  922.  
  923.                             }
  924.                     }
  925.                 }
  926.  
  927.             }
  928.     }
  929.  
  930.  
  931. void aftereven(struct board *board)
  932.     {
  933.     short x1,y1,q1,px,py,aftereven;
  934.     short sln,*grp,j,x,cols,cl[4],pj;
  935.  
  936.     for(y1=1;y1<BOARDY;y1+=2)
  937.         for(x1=0;x1<BOARDX;x1++)
  938.             {
  939.             q1=ELM(x1,y1);
  940.             if(!board->sqused[q1]) continue;
  941.  
  942.             sln=board->solvable_groups->sqpnt[q1];
  943.             grp=board->solvable_groups->square[q1];
  944.  
  945.             for(j=0;j<sln;j++)
  946.                 {
  947.                 if(board->intgp.mygroups[grp[j]]==YES &&
  948.                     x1==board->xplace[grp[j]][0] &&
  949.                     x1<board->xplace[grp[j]][3])
  950.                         {
  951.                         aftereven=YES;
  952.                         cols=0;
  953.                         memset(cl,0xff,8);
  954.  
  955.                         for(x=0;x<TILES && aftereven;x++)
  956.                             {
  957.                             px=board->xplace[grp[j]][x];
  958.                             py=board->yplace[grp[j]][x];
  959.  
  960.                             if(board->sqused[ELM(px,py)]==NO) aftereven=NO;
  961.  
  962.                             if(board->square[ELM(px,py)]==EMPTY)
  963.                                 {
  964.                                 if((py&1)==1 && board->stack[px]<=py-1)
  965.                                     cl[cols++]=ELM(px,py);
  966.                                 else aftereven=NO;
  967.                                 }
  968.                             }
  969.  
  970.                         if(aftereven && cols>0)
  971.                             {
  972.                             board->solution[board->sp]->solgroupsnumb=0;
  973.                             board->solution[board->sp]->solname=AFTEREVEN;
  974.                             board->solution[board->sp]->solpoint[0]=q1;
  975.                             board->solution[board->sp]->solpoint[1]=ELM(board->xplace[grp[j]][3],board->yplace[grp[j]][3]);
  976.                             board->instances[AFTEREVEN]++;
  977.  
  978.                             board->solution[board->sp]->sqinvnumb=cols;
  979.                             for(pj=0;pj<cols;pj++)
  980.                                 board->solution[board->sp]->sqinv[pj]=cl[pj];
  981.  
  982.                             solve_columns(board,cols,cl);
  983.                             if(board->solution[board->sp]->solgroupsnumb>0) board->sp++;
  984.                             }
  985.                         }
  986.                 }
  987.  
  988.             }
  989.     }
  990.  
  991.  
  992. void lowinverse(struct board *board)
  993.     {
  994.     short x1,y1,q1,q2,px,py,wx,wy;
  995.     short sln,*grp,j,k,x,y;
  996.     char set[64];
  997.  
  998.     for(y1=2;y1<BOARDY;y1+=2)
  999.         for(x1=0;x1<BOARDX;x1++)
  1000.             {
  1001.             q1=ELM(x1,y1);
  1002.             if(!board->sqused[q1]) continue;
  1003.  
  1004.             if(board->stack[x1]<y1)
  1005.                 {
  1006.                 memset(set,YES,64);
  1007.  
  1008.                 sln=board->solvable_groups->sqpnt[q1];
  1009.                 grp=board->solvable_groups->square[q1];
  1010.  
  1011.                 for(j=0;j<sln;j++)
  1012.                     {
  1013.                     if(board->intgp.tgroups[grp[j]]==YES &&
  1014.                         board->xplace[grp[j]][0]!=board->xplace[grp[j]][3])
  1015.                         {
  1016.                         for(x=0;x<TILES;x++)
  1017.                             {
  1018.                             wx=board->xplace[grp[j]][x];
  1019.                             wy=board->yplace[grp[j]][x];
  1020.  
  1021.                             if(x1<wx && board->stack[wx]<wy && wy>0 &&
  1022.                                 (wy&1)==0 && set[ELM(wx,wy)] &&
  1023.                                 board->sqused[ELM(wx,wy)])
  1024.                                 {
  1025.                                 set[ELM(wx,wy)]=NO;
  1026.                                 board->solution[board->sp]->solgroupsnumb=0;
  1027.                                 board->solution[board->sp]->solname=LOWINVERSE;
  1028.                                 board->solution[board->sp]->solpoint[0]=q1;
  1029.                                 board->solution[board->sp]->solpoint[1]=ELM(wx,wy);
  1030.                                 board->solution[board->sp]->sqinv[0]=q1;
  1031.                                 board->solution[board->sp]->sqinv[1]=ELM(wx,wy);
  1032.                                 board->solution[board->sp]->sqinv[2]=ELM(x1,y1-1);
  1033.                                 board->solution[board->sp]->sqinv[3]=ELM(wx,wy-1);
  1034.                                 board->solution[board->sp]->sqinvnumb=4;
  1035.                                 both_groups(board,q1,ELM(wx,wy));
  1036.                                 both_groups(board,q1,ELM(x1,y1-1));
  1037.                                 both_groups(board,ELM(wx,wy),ELM(wx,wy-1));
  1038.                                 board->instances[LOWINVERSE]++;
  1039.                                 if(board->solution[board->sp]->solgroupsnumb>0) board->sp++;
  1040.                                 }
  1041.                             }
  1042.                         }
  1043.                     }
  1044.                 }
  1045.             }
  1046.     }
  1047.  
  1048. void highinverse(struct board *board)
  1049.     {
  1050.     short x1,y1,q1,q2,px,py,wx,wy;
  1051.     short sln,*grp,j,k,x,y;
  1052.     char set[64];
  1053.  
  1054.     for(y1=2;y1<BOARDY;y1+=2)
  1055.         for(x1=0;x1<BOARDX;x1++)
  1056.             {
  1057.             q1=ELM(x1,y1);
  1058.             if(!board->sqused[q1]) continue;
  1059.  
  1060.             if(board->stack[x1]<y1)
  1061.                 {
  1062.                 memset(set,YES,64);
  1063.  
  1064.                 sln=board->solvable_groups->sqpnt[q1];
  1065.                 grp=board->solvable_groups->square[q1];
  1066.  
  1067.                 for(j=0;j<sln;j++)
  1068.                     {
  1069.                     if(board->intgp.tgroups[grp[j]]==YES &&
  1070.                         board->xplace[grp[j]][0]!=board->xplace[grp[j]][3])
  1071.                         {
  1072.                         for(x=0;x<TILES;x++)
  1073.                             {
  1074.                             wx=board->xplace[grp[j]][x];
  1075.                             wy=board->yplace[grp[j]][x];
  1076.  
  1077.                             if(x1<wx && board->stack[wx]<wy && wy>0 &&
  1078.                                 (wy&1)==0 && set[ELM(wx,wy)] &&
  1079.                                 board->sqused[ELM(wx,wy)])
  1080.                                 {
  1081.                                 set[ELM(wx,wy)]=NO;
  1082.                                 board->solution[board->sp]->solgroupsnumb=0;
  1083.                                 board->solution[board->sp]->solname=HIGHINVERSE;
  1084.                                 board->solution[board->sp]->solpoint[0]=q1;
  1085.                                 board->solution[board->sp]->solpoint[1]=ELM(wx,wy);
  1086.                                 board->solution[board->sp]->sqinv[0]=q1;
  1087.                                 board->solution[board->sp]->sqinv[1]=ELM(wx,wy);
  1088.                                 board->solution[board->sp]->sqinv[2]=ELM(x1,y1-1);
  1089.                                 board->solution[board->sp]->sqinv[3]=ELM(wx,wy-1);
  1090.                                 board->solution[board->sp]->sqinv[4]=ELM(x1,y1+1);
  1091.                                 board->solution[board->sp]->sqinv[5]=ELM(wx,wy+1);
  1092.                                 board->solution[board->sp]->sqinvnumb=6;
  1093.                                 board->instances[HIGHINVERSE]++;
  1094.  
  1095.                                 /* Upper and middle squares */
  1096.                                 both_groups(board,ELM(x1,y1+1),ELM(wx,wy+1));
  1097.                                 both_groups(board,q1,ELM(wx,wy));
  1098.  
  1099.                                 /* Vertical groups */
  1100.                                 both_groups(board,ELM(x1,y1),ELM(x1,y1+1));
  1101.                                 both_groups(board,ELM(wx,wy),ELM(wx,wy+1));
  1102.  
  1103.                                 /* Lower 1st and Upper 2nd if lower is playable */
  1104.                                 if(board->stack[x1]==y1-1)
  1105.                                     both_groups(board,ELM(x1,y1-1),ELM(wx,wy+1));
  1106.  
  1107.                                 /* Upper 1st and Lower 2nd if lower is playable */
  1108.                                 if(board->stack[wx]==wy-1)
  1109.                                     both_groups(board,ELM(x1,y1+1),ELM(wx,wy-1));
  1110.  
  1111.                                 if(board->solution[board->sp]->solgroupsnumb>0) board->sp++;
  1112.                                 }
  1113.                             }
  1114.                         }
  1115.                     }
  1116.                 }
  1117.             }
  1118.     }
  1119.  
  1120.  
  1121. void baseclaim(struct board *board)
  1122.     {
  1123.     short x1,y1,q1,q2,px,py,wx,wy;
  1124.     short sln,*grp,j,k,x,y,cl[6],cols;
  1125.     char set[64];
  1126.  
  1127.     memset(set,YES,64);
  1128.     for(y1=0;y1<BOARDY;y1++)
  1129.         for(x1=0;x1<BOARDX;x1++)
  1130.             {
  1131.             if(!board->sqused[ELM(x1,y1)]) continue;
  1132.             if(board->stack[x1]==y1)
  1133.                 {
  1134.                 q1=ELM(x1,y1);
  1135.  
  1136.                 sln=board->solvable_groups->sqpnt[q1];
  1137.                 grp=board->solvable_groups->square[q1];
  1138.  
  1139.                 for(j=0;j<sln;j++)
  1140.                     {
  1141.                     if(board->intgp.tgroups[grp[j]]==YES &&
  1142.                         board->xplace[grp[j]][0]!=board->xplace[grp[j]][3])
  1143.                         {
  1144.                         cols=0;
  1145.  
  1146.                         for(x=0;x<TILES;x++)
  1147.                             {
  1148.                             wx=board->xplace[grp[j]][x];
  1149.                             wy=board->yplace[grp[j]][x];
  1150.  
  1151.                             if(board->sqused[ELM(wx,wy)]==0) continue;
  1152.                             if(board->stack[wx]==wy) cl[cols++]=ELM(wx,wy);
  1153.                             }
  1154.  
  1155.                         if(cols!=3) continue;
  1156.                         else
  1157.                             {
  1158.                             cl[3]=cl[1];
  1159.                             cl[4]=cl[0];
  1160.  
  1161.                             if(set[cl[0]]) check_claim(board,&cl[0]);
  1162.  
  1163.                             set[cl[0]]=NO;
  1164.                             }                                      }
  1165.                     }
  1166.                 }
  1167.             }
  1168.     }
  1169.  
  1170.  
  1171. void before(struct board *board)
  1172.     {
  1173.     short j,px,py,before;
  1174.     short x,cols,cl[TILES];
  1175.  
  1176.     for(j=0;j<GROUPS;j++)
  1177.         {
  1178.         if(!board->intgp.mygroups[j] ||
  1179.             board->xplace[j][0]==board->xplace[j][3] ||
  1180.             board->yplace[j][0]==BOARDY-1 ||
  1181.             board->yplace[j][3]==BOARDY-1) continue;
  1182.  
  1183.         cols=0;
  1184.         before=YES;
  1185.  
  1186.         for(x=0;x<TILES && before;x++)
  1187.             {
  1188.             px=board->xplace[j][x];
  1189.             py=board->yplace[j][x];
  1190.  
  1191.             if(!board->sqused[ELM(px,py)]) before=NO;
  1192.             else if(board->square[ELM(px,py)]==EMPTY)
  1193.                 cl[cols++]=ELM(px,py+1);
  1194.  
  1195.             }
  1196.  
  1197.         if(before && cols>0)
  1198.             {
  1199.             for(x=0;x<cols;x++)
  1200.                 board->solution[board->sp]->sqinv[x]=cl[x];
  1201.  
  1202.             generate_all_other_before_instances(board,cols,cl,j);
  1203.             }
  1204.         }
  1205.     }
  1206. /*
  1207.  
  1208. void before(struct board *board)
  1209.     {
  1210.     short x1,y1,q1,px,py,before,pj,fx,fy;
  1211.     short sln,*grp,j,x,cols,cl[TILES];
  1212.  
  1213.     for(y1=0;y1<BOARDY;y1++)
  1214.         for(x1=0;x1<BOARDX;x1++)
  1215.             {
  1216.             q1=ELM(x1,y1);
  1217.             if(!board->sqused[q1]) continue;
  1218.  
  1219.             sln=board->solvable_groups->sqpnt[q1];
  1220.             grp=board->solvable_groups->square[q1];
  1221.  
  1222.             for(j=0;j<sln;j++)
  1223.                 {
  1224.                 if(board->intgp.mygroups[grp[j]]==YES &&
  1225.                     x1==board->xplace[grp[j]][0] &&
  1226.                     x1<board->xplace[grp[j]][3])
  1227.                         {
  1228.                         before=YES;
  1229.                         cols=0;
  1230.                         memset(cl,0xff,8);
  1231.  
  1232.                         for(x=0;x<TILES && before;x++)
  1233.                             {
  1234.                             px=board->xplace[grp[j]][x];
  1235.                             py=board->yplace[grp[j]][x];
  1236.  
  1237.                             if(board->square[ELM(px,py)]==EMPTY)
  1238.                                 {
  1239.                                 if(py<BOARDY-1) cl[cols++]=ELM(px,py+1);
  1240.                                 else before=NO;
  1241.                                 }
  1242.                             }
  1243.  
  1244.  
  1245.                         if(before && cols>0)
  1246.                             {
  1247.                             for(pj=0;pj<cols;pj++)
  1248.                                 board->solution[board->sp]->sqinv[pj]=cl[pj];
  1249.  
  1250.                             generate_all_other_before_instances(board,cols,cl,grp[j]);
  1251.                             }
  1252.                         }
  1253.                 }
  1254.  
  1255.             }
  1256.     }
  1257.  
  1258.  
  1259. /* --------------------------------------------------------------- */
  1260.  
  1261. short threat_group(struct board *board,short group,short who)
  1262.     {
  1263.     short p;
  1264.  
  1265.     p=((*board->groups[group][0])|(*board->groups[group][1])|
  1266.         (*board->groups[group][2])|(*board->groups[group][3]));
  1267.  
  1268.     if(p&who) return NO;
  1269.     return YES;
  1270.     }
  1271.  
  1272. /* -------------------------------------------------------------------- */
  1273.  
  1274. short check_early_win(struct board *board)
  1275.     {
  1276.     if(board->square[SQ_d1]==WHITE &&
  1277.         board->square[SQ_c3]==WHITE &&
  1278.         board->square[SQ_e3]==WHITE &&
  1279.         (board->square[SQ_c2]==WHITE || board->square[SQ_e2]==WHITE) &&
  1280.         board->square[SQ_b2]==EMPTY &&
  1281.         board->square[SQ_d2]==EMPTY &&
  1282.         board->square[SQ_f2]==EMPTY) return YES;
  1283.  
  1284.     return NO;
  1285.     }
  1286.  
  1287. short anypentas(struct board *board)
  1288.     {
  1289.     short an=0;
  1290.  
  1291.     if(board->square[SQ_c1]!=WHITE && board->square[SQ_e1]!=WHITE) return 0;
  1292.  
  1293.     if(board->square[SQ_b3]==WHITE &&
  1294.         board->square[SQ_d3]==WHITE &&
  1295.         (board->square[SQ_b2]==WHITE || board->square[SQ_d2]==WHITE) &&
  1296.         board->square[SQ_a2]==EMPTY &&
  1297.         board->square[SQ_c2]==EMPTY &&
  1298.         board->square[SQ_e2]==EMPTY) an|=2;
  1299.  
  1300.     if(board->square[SQ_d3]==WHITE &&
  1301.         board->square[SQ_f3]==WHITE &&
  1302.         (board->square[SQ_d2]==WHITE || board->square[SQ_f2]==WHITE) &&
  1303.         board->square[SQ_c2]==EMPTY &&
  1304.         board->square[SQ_e2]==EMPTY &&
  1305.         board->square[SQ_g2]==EMPTY) an|=1;
  1306.  
  1307.     return an;
  1308.     }
  1309.  
  1310. void dump_instances(struct board *board)
  1311.     {
  1312.     short x,y,i,px1,py1,px2,py2;
  1313.  
  1314.     for(x=1;x<=9;x++)
  1315.         {
  1316.         printf("%13s ",rulename[x-1]);
  1317.  
  1318.         for(y=0;y<board->sp;y++)
  1319.             {
  1320.             if(board->solution[y]->solname==x)
  1321.                 {
  1322.                 px1=ELX(board->solution[y]->solpoint[0]);
  1323.                 py1=ELY(board->solution[y]->solpoint[0]);
  1324.                 px2=ELX(board->solution[y]->solpoint[1]);
  1325.                 py2=ELY(board->solution[y]->solpoint[1]);
  1326.  
  1327.                 printf("(%c%d,%c%d) ",px1+65,py1+1,px2+65,py2+1);
  1328.                 }
  1329.             }
  1330.         printf("\n\r");
  1331.         }
  1332.     }
  1333.  
  1334. void ss_dump_instances(struct board *board,FILE *h1)
  1335.     {
  1336.     short x,y,i,px1,py1,px2,py2;
  1337.  
  1338.     for(x=1;x<=9;x++)
  1339.         {
  1340.         fprintf(h1,"%13s ",rulename[x-1]);
  1341.  
  1342.         for(y=0;y<board->sp;y++)
  1343.             {
  1344.             if(board->solution[y]->solname==x)
  1345.                 {
  1346.                 px1=ELX(board->solution[y]->solpoint[0]);
  1347.                 py1=ELY(board->solution[y]->solpoint[0]);
  1348.                 px2=ELX(board->solution[y]->solpoint[1]);
  1349.                 py2=ELY(board->solution[y]->solpoint[1]);
  1350.  
  1351.                 fprintf(h1,"(%c%d,%c%d) ",px1+65,py1+1,px2+65,py2+1);
  1352.                 }
  1353.             }
  1354.         fprintf(h1,"\n\r");
  1355.         }
  1356.     }
  1357.  
  1358. void dump_solutions(struct board *board,short sol)
  1359.     {
  1360.     short x,y,px1,px2,py1,py2,gp,k,found=0;
  1361.     FILE *h1;
  1362.  
  1363.     h1=fopen(LOGFILE,"a+");
  1364.     if(!h1) fatal_error("Cannot open logfile");
  1365.  
  1366.     printf("\n\r");
  1367.     printf("%s\n\r",rulename[sol-1]);
  1368.  
  1369.     fprintf(h1,"\n");
  1370.     fprintf(h1,"%s\n",rulename[sol-1]);
  1371.  
  1372.     for(x=0;x<board->sp;x++)
  1373.         {
  1374.         if(board->solution[x]->solname==sol)
  1375.             {
  1376.             found++;
  1377.  
  1378.             px1=ELX(board->solution[x]->solpoint[0]);
  1379.             py1=ELY(board->solution[x]->solpoint[0]);
  1380.             px2=ELX(board->solution[x]->solpoint[1]);
  1381.             py2=ELY(board->solution[x]->solpoint[1]);
  1382.  
  1383.             printf("(%c%d,%c%d) [%3d]--> ",px1+65,py1+1,px2+65,py2+1,x);
  1384.             fprintf(h1,"(%c%d,%c%d) [%3d]--> ",px1+65,py1+1,px2+65,py2+1,x);
  1385.  
  1386.             for(y=0;y<board->solution[x]->solgroupsnumb;y++)
  1387.                 {
  1388.                 gp=board->solution[x]->solgroups[y];
  1389.  
  1390.                 px1=board->xplace[gp][0];
  1391.                 py1=board->yplace[gp][0];
  1392.                 px2=board->xplace[gp][3];
  1393.                 py2=board->yplace[gp][3];
  1394.  
  1395.                 printf("%c%d%c%d  ",px1+97,py1+1,px2+97,py2+1);
  1396.                 fprintf(h1,"%c%d%c%d  ",px1+97,py1+1,px2+97,py2+1);
  1397.                 }
  1398.  
  1399.             printf("\n\r");
  1400.             fprintf(h1,"\n");
  1401.             for(k=0;k<board->solution[x]->sqinvnumb;k++)
  1402.                 {
  1403.                 gp=board->solution[x]->sqinv[k];
  1404.                 printf("%c%d ",ELX(gp)+97,ELY(gp)+1);
  1405.                 fprintf(h1,"%c%d ",ELX(gp)+97,ELY(gp)+1);
  1406.                 }
  1407.  
  1408.             printf("\n\r");
  1409.             fprintf(h1,"\n");
  1410.             }
  1411.         }
  1412.  
  1413.     printf("\n\r");
  1414.     fprintf(h1,"\n");
  1415.  
  1416.     printf("Total solution found of specified kind: %d\n\r",found);
  1417.     fprintf(h1,"Total solution found of specified kind: %d\n",found);
  1418.  
  1419.     printf("Output end.\n\r");
  1420.  
  1421.     fclose(h1);
  1422.     }
  1423.  
  1424. void debug_black(struct board *board)
  1425.     {
  1426.     short key,oracle;
  1427.     register x;
  1428.     char **matrix;
  1429.     short i,*bpos;
  1430.  
  1431.  
  1432.     board->sp=0;
  1433.  
  1434.     board->intgp.j=0;
  1435.     board->intgp.k=0;
  1436.  
  1437.     memset(board->sqused,0xff,(BOARDX+1)*(BOARDY+2)*sizeof(short));
  1438.  
  1439.     for(i=0;i<GROUPS;i++)
  1440.         {
  1441.         if(threat_group(board,i,BLACK))
  1442.             {
  1443.             board->intgp.tgroups[i]=YES;
  1444.             board->intgp.j++;
  1445.             }
  1446.         else board->intgp.tgroups[i]=NO;
  1447.  
  1448.         if(threat_group(board,i,WHITE))
  1449.             {
  1450.             board->intgp.mygroups[i]=YES;
  1451.             board->intgp.k++;
  1452.             }
  1453.         else board->intgp.mygroups[i]=NO;
  1454.         }
  1455.  
  1456.     claimeven(board);
  1457.     baseinverse(board);
  1458.     vertical(board);
  1459.     aftereven(board);
  1460.     lowinverse(board);
  1461.     highinverse(board);
  1462.     baseclaim(board);
  1463.     before(board);
  1464.  
  1465.     dump_instances(board);
  1466.     dump_file_board(board);
  1467.  
  1468.     matrix=(char **)allocate_matrix(board);
  1469.     build_adjacency_matrix(matrix,board);
  1470.  
  1471.     oracle=problem_solver(board,matrix,NO,NULL);
  1472.  
  1473.     printf("\n\r");
  1474.     printf("Total sol. found : %d, total dangerous groups %d, groups solved %d\n\r",
  1475.                 board->sp,board->intgp.j,board->problem_solved);
  1476.     printf("Oracle spits out %d\n\r",oracle);
  1477.  
  1478.     printf("Key 1 - 9 to see rules instances, ESC to return to game play\n\r");
  1479.     printf("j to dump the non adjacencies, t to test rule compatibility\n\r");
  1480.  
  1481.     while((key=readkey())!=0x1b)
  1482.         {
  1483.         switch(key)
  1484.             {
  1485.             case '1':
  1486.                 dump_solutions(board,CLAIMEVEN);
  1487.                 break;
  1488.  
  1489.             case '2':
  1490.                 dump_solutions(board,BASEINVERSE);
  1491.                 break;
  1492.  
  1493.             case '3':
  1494.                 dump_solutions(board,VERTICAL);
  1495.                 break;
  1496.  
  1497.             case '4':
  1498.                 dump_solutions(board,AFTEREVEN);
  1499.                 break;
  1500.  
  1501.             case '5':
  1502.                 dump_solutions(board,LOWINVERSE);
  1503.                 break;
  1504.  
  1505.             case '6':
  1506.                 dump_solutions(board,HIGHINVERSE);
  1507.                 break;
  1508.  
  1509.             case '7':
  1510.                 dump_solutions(board,BASECLAIM);
  1511.                 break;
  1512.  
  1513.             case '8':
  1514.                 dump_solutions(board,BEFORE);
  1515.                 break;
  1516.  
  1517.             case '9':
  1518.                 dump_solutions(board,SPECIALBEFORE);
  1519.                 break;
  1520.  
  1521.             case 'j':
  1522.                 dump_no_adjacencies(matrix,board);
  1523.                 break;
  1524.  
  1525.             case 't':
  1526.                 test_conditions(matrix,board);
  1527.                 break;
  1528.             }
  1529.         }
  1530.  
  1531.     free_matrix(matrix,board);
  1532.     }
  1533.  
  1534.  
  1535. void debug_white(struct board *board)
  1536.     {
  1537.     short x,y,x1,y1,f,g,j;
  1538.     struct threat_combo tc[GROUPS];
  1539.     short threats[GROUPS],thnumb,anythreat=0,ccmb;
  1540.     short key,oracle,combo,pentas;
  1541.     char **matrix;
  1542.     short i,*bpos,px,py;
  1543.  
  1544.     if(check_early_win(board))
  1545.         {
  1546.         printf("An early win is detected! (ESC to return)\n\r");
  1547.         while(readkey()!=0x1b);
  1548.         return;
  1549.         }
  1550.  
  1551.     pentas=0;
  1552.     combo=threat_combo(board,tc);
  1553.  
  1554.     thnumb=count_odd_threats(board,threats);
  1555.     if(thnumb+combo==0 && !pentas)
  1556.         {
  1557.         printf("No decisive threats, (ESC to return)\n\r");
  1558.         while(readkey()!=0x1b);
  1559.         return;
  1560.         }
  1561.  
  1562.     do
  1563.         {
  1564.         memset(board->usablegroup,0xff,GROUPS*sizeof(short));
  1565.         memset(board->sqused,0xff,(BOARDX+1)*(BOARDY+2)*sizeof(short));
  1566.         memset(board->wipesq,0x00,(BOARDX+1)*(BOARDY+2)*sizeof(short));
  1567.  
  1568.         if(anythreat<thnumb)
  1569.             {
  1570.             wipe_above(board,threats[anythreat]);
  1571.             wipe_odd(board,threats[anythreat]);
  1572.  
  1573.             px=ELX(threats[anythreat]);
  1574.             for(py=0;py<BOARDY;py++)
  1575.                 if(board->square[ELM(px,py)]==EMPTY)
  1576.                     board->sqused[ELM(px,py)]=NO;
  1577.             }
  1578.         else if(anythreat<thnumb+combo)
  1579.             {
  1580.             ccmb=anythreat-thnumb;
  1581.  
  1582.             px=ELX(tc[ccmb].cross);
  1583.             x =ELX(tc[ccmb].odd);
  1584.  
  1585.             for(y=0;y<BOARDY;y++)
  1586.                 {
  1587.                 if(board->square[ELM(px,y)]==EMPTY)
  1588.                     board->sqused[ELM(px,y)]=NO;
  1589.  
  1590.                 if(board->square[ELM( x,y)]==EMPTY)
  1591.                     board->sqused[ELM( x,y)]=NO;
  1592.                 }
  1593.  
  1594.             if(ELY(tc[ccmb].even)>ELY(tc[ccmb].odd))
  1595.                 handle_even_above_odd(board,&tc[ccmb]);
  1596.             else handle_odd_above_even(board,&tc[ccmb]);
  1597.             }
  1598.         else fatal_error("What am I doing?");
  1599.  
  1600.         board->sp=0;
  1601.         board->intgp.j=0;
  1602.         board->intgp.k=0;
  1603.  
  1604.         for(i=0;i<GROUPS;i++)
  1605.             {
  1606.             if(threat_group(board,i,WHITE) &&
  1607.                 !wiped_group(board,i) && board->usablegroup[i])
  1608.                 {
  1609.                 board->intgp.tgroups[i]=YES;
  1610.                 board->intgp.j++;
  1611.                 }
  1612.             else board->intgp.tgroups[i]=NO;
  1613.  
  1614.             if(threat_group(board,i,BLACK))
  1615.                 {
  1616.                 board->intgp.mygroups[i]=YES;
  1617.                 board->intgp.k++;
  1618.                 }
  1619.             else board->intgp.mygroups[i]=NO;
  1620.             }
  1621.  
  1622.         claimeven(board);
  1623.         baseinverse(board);
  1624.         vertical(board);
  1625.         aftereven(board);
  1626.         lowinverse(board);
  1627.         highinverse(board);
  1628.         baseclaim(board);
  1629.         before(board);
  1630.  
  1631.         dump_instances(board);
  1632.         dump_file_board(board);
  1633.  
  1634.         if(anythreat<thnumb) dump_file_threat(board,anythreat);
  1635.  
  1636.         matrix=(char **)allocate_matrix(board);
  1637.         build_adjacency_matrix(matrix,board);
  1638.  
  1639.         oracle=problem_solver(board,matrix,NO,NULL);
  1640.  
  1641.         printf("\n\r");
  1642.         printf("Total sol. found : %d, total dangerous groups %d, groups solved %d\n\r",
  1643.                 board->sp,board->intgp.j,board->problem_solved);
  1644.  
  1645.  
  1646.         if(anythreat<thnumb)
  1647.             {
  1648.             printf("Odd threat at %c%d, oracle spits out %d\n\r",
  1649.                         ELX(threats[anythreat])+97,ELY(threats[anythreat])+1,oracle);
  1650.             }
  1651.         else if(anythreat<thnumb+combo)
  1652.             {
  1653.             printf("Double odd threat at %c%d, oracle spits out %d\n\r",
  1654.                         ELX(tc[anythreat-thnumb].cross)+97,ELY(tc[anythreat-thnumb].cross)+1,oracle);
  1655.             }
  1656.         else
  1657.             {
  1658.             printf("Pentas found.\n\r",pentas);
  1659.             }
  1660.  
  1661.  
  1662.         printf("1 - 9 to see rules instances, ESC to return to game play\n");
  1663.         printf("j to dump the non adjacencies, t to test rule compatibility\n");
  1664.         printf("s to show squares available\n");
  1665.  
  1666.         while((key=readkey())!=0x1b)
  1667.             {
  1668.             switch(key)
  1669.                 {
  1670.                 case '1':
  1671.                     dump_solutions(board,CLAIMEVEN);
  1672.                     break;
  1673.  
  1674.                 case '2':
  1675.                     dump_solutions(board,BASEINVERSE);
  1676.                     break;
  1677.  
  1678.                 case '3':
  1679.                     dump_solutions(board,VERTICAL);
  1680.                     break;
  1681.  
  1682.                 case '4':
  1683.                     dump_solutions(board,AFTEREVEN);
  1684.                     break;
  1685.  
  1686.                 case '5':
  1687.                     dump_solutions(board,LOWINVERSE);
  1688.                     break;
  1689.  
  1690.                 case '6':
  1691.                     dump_solutions(board,HIGHINVERSE);
  1692.                     break;
  1693.  
  1694.                 case '7':
  1695.                     dump_solutions(board,BASECLAIM);
  1696.                     break;
  1697.  
  1698.                 case '8':
  1699.                     dump_solutions(board,BEFORE);
  1700.                     break;
  1701.  
  1702.                 case '9':
  1703.                     dump_solutions(board,SPECIALBEFORE);
  1704.                     break;
  1705.  
  1706.                 case 'j':
  1707.                     dump_no_adjacencies(matrix,board);
  1708.                     break;
  1709.  
  1710.                 case 't':
  1711.                     test_conditions(matrix,board);
  1712.                     break;
  1713.  
  1714.                 case 's':
  1715.                     show_square_used(board);
  1716.                     break;
  1717.  
  1718.                 }
  1719.             }
  1720.  
  1721.         free_matrix(matrix,board);
  1722.         anythreat++;
  1723.         } while(anythreat<thnumb+combo || pentas);
  1724.  
  1725.     }
  1726.  
  1727. void debug_function(struct board *board)
  1728.     {
  1729.     clrscr();
  1730.     switch(board->turn)
  1731.         {
  1732.         case WHITE:
  1733.             debug_black(board);
  1734.             break;
  1735.  
  1736.         case BLACK:
  1737.             debug_white(board);
  1738.             break;
  1739.  
  1740.         }
  1741.     }
  1742.  
  1743.  
  1744. /* -------------------------------------------------------------------- */
  1745.  
  1746. // Main evaluation function for the oracle
  1747.  
  1748. short evaluate_black(struct board *board)
  1749.     {
  1750.     short key,oracle;
  1751.     register x;
  1752.     char **matrix;
  1753.     short i,*bpos;
  1754.  
  1755.     board->sp=0;
  1756.  
  1757.     board->intgp.j=0;
  1758.     board->intgp.k=0;
  1759.  
  1760.     memset(board->sqused,0xff,(BOARDX+1)*(BOARDY+2)*sizeof(short));
  1761.  
  1762.     for(i=0;i<GROUPS;i++)
  1763.         {
  1764.         if(threat_group(board,i,BLACK))
  1765.             {
  1766.             board->intgp.tgroups[i]=YES;
  1767.             board->intgp.j++;
  1768.             }
  1769.         else board->intgp.tgroups[i]=NO;
  1770.  
  1771.         if(threat_group(board,i,WHITE))
  1772.             {
  1773.             board->intgp.mygroups[i]=YES;
  1774.             board->intgp.k++;
  1775.             }
  1776.         else board->intgp.mygroups[i]=NO;
  1777.         }
  1778.  
  1779.     claimeven(board);
  1780.     baseinverse(board);
  1781.     vertical(board);
  1782.     aftereven(board);
  1783.     lowinverse(board);
  1784.     highinverse(board);
  1785.     baseclaim(board);
  1786.     before(board);
  1787.  
  1788.     if(board->intgp.j==0) return YES;
  1789.     if(board->sp==0) return NO;
  1790.  
  1791.     matrix=(char **)allocate_matrix(board);
  1792.     build_adjacency_matrix(matrix,board);
  1793.  
  1794.     oracle=problem_solver(board,matrix,NO,NULL);
  1795.     free_matrix(matrix,board);
  1796.  
  1797.     return oracle;
  1798.     }
  1799.  
  1800.  
  1801. short evaluate_white(struct board *board)
  1802.     {
  1803.     short x,y;
  1804.     struct threat_combo tc[GROUPS];
  1805.     short threats[MAXGROUPS],thnum=0,combo,ccmb;
  1806.     short key,oracle,anythreat=0;
  1807.     char **matrix;
  1808.     short i,*bpos,px,py;
  1809.  
  1810.     combo=threat_combo(board,tc);
  1811.     thnum=count_odd_threats(board,threats);
  1812.     if(thnum+combo==0) return NO;
  1813.  
  1814.     do
  1815.         {
  1816.         memset(board->usablegroup,0xff,GROUPS*sizeof(short));
  1817.         memset(board->sqused,0xff,(BOARDX+1)*(BOARDY+2)*sizeof(short));
  1818.         memset(board->wipesq,0x00,(BOARDX+1)*(BOARDY+2)*sizeof(short));
  1819.  
  1820.         if(anythreat<thnum)
  1821.             {
  1822.             wipe_above(board,threats[anythreat]);
  1823.             wipe_odd(board,threats[anythreat]);
  1824.  
  1825.             px=ELX(threats[anythreat]);
  1826.             for(py=0;py<BOARDY;py++)
  1827.                 if(board->square[ELM(px,py)]==EMPTY)
  1828.                     board->sqused[ELM(px,py)]=NO;
  1829.             }
  1830.         else
  1831.             {
  1832.             ccmb=anythreat-thnum;
  1833.  
  1834.             px=ELX(tc[ccmb].cross);
  1835.             x =ELX(tc[ccmb].odd);
  1836.  
  1837.             for(y=0;y<BOARDY;y++)
  1838.                 {
  1839.                 if(board->square[ELM(px,y)]==EMPTY)
  1840.                     board->sqused[ELM(px,y)]=NO;
  1841.  
  1842.                 if(board->square[ELM( x,y)]==EMPTY)
  1843.                     board->sqused[ELM( x,y)]=NO;
  1844.                 }
  1845.  
  1846.             if(ELY(tc[ccmb].even)>ELY(tc[ccmb].odd))
  1847.                 handle_even_above_odd(board,&tc[ccmb]);
  1848.             else
  1849.                 handle_odd_above_even(board,&tc[ccmb]);
  1850.             }
  1851.  
  1852.         board->sp=0;
  1853.         board->intgp.j=0;
  1854.         board->intgp.k=0;
  1855.  
  1856.         for(i=0;i<GROUPS;i++)
  1857.             {
  1858.             if(threat_group(board,i,WHITE) &&
  1859.                 !wiped_group(board,i) && board->usablegroup[i])
  1860.                 {
  1861.                 board->intgp.tgroups[i]=YES;
  1862.                 board->intgp.j++;
  1863.                 }
  1864.             else board->intgp.tgroups[i]=NO;
  1865.  
  1866.             if(threat_group(board,i,BLACK))
  1867.                 {
  1868.                 board->intgp.mygroups[i]=YES;
  1869.                 board->intgp.k++;
  1870.             }
  1871.             else board->intgp.mygroups[i]=NO;
  1872.             }
  1873.  
  1874.         for(y=0;y<BOARDY;y++)
  1875.             for(x=0;x<BOARDX;x++)
  1876.                 if(board->square[ELM(x,y)]!=EMPTY &&
  1877.                    board->sqused[ELM(x,y)]==NO)
  1878.                       fatal_error("Marked as used an useless square...");
  1879.  
  1880.         claimeven(board);
  1881.         baseinverse(board);
  1882.         vertical(board);
  1883.         aftereven(board);
  1884.         lowinverse(board);
  1885.         highinverse(board);
  1886.         baseclaim(board);
  1887.         before(board);
  1888.  
  1889.         if(board->intgp.j==0) oracle=YES;
  1890.         else if(board->sp==0) oracle=NO;
  1891.         else
  1892.             {
  1893.             matrix=(char **)allocate_matrix(board);
  1894.             build_adjacency_matrix(matrix,board);
  1895.  
  1896.             oracle=problem_solver(board,matrix,NO,NULL);
  1897.             free_matrix(matrix,board);
  1898.             }
  1899.  
  1900.         anythreat++;
  1901.         } while(anythreat<thnum+combo && oracle==NO);
  1902.  
  1903.     return oracle;
  1904.     }
  1905.  
  1906.  
  1907. short evaluation_function(struct board *board)
  1908.     {
  1909.     switch(board->turn)
  1910.         {
  1911.         case WHITE:
  1912.             return evaluate_black(board);
  1913.  
  1914.         case BLACK:
  1915.             return evaluate_white(board);
  1916.         }
  1917.  
  1918.     return NOCOMMENT;
  1919.     }
  1920.  
  1921. // *************************************************************************
  1922.  
  1923. // Single step evaluation to file
  1924.  
  1925. short ss_evaluate_black(struct board *board)
  1926.     {
  1927.     FILE *h1;
  1928.     short key,oracle;
  1929.     register x;
  1930.     char **matrix;
  1931.     short i,*bpos;
  1932.  
  1933.     h1=fopen(TMPFILENAME,"w");
  1934.     if(!h1) fatal_error("Cannot open temporary file");
  1935.  
  1936.     fprintf(h1,"Oracle analysis for red:\n\n");
  1937.  
  1938.     board->sp=0;
  1939.  
  1940.     board->intgp.j=0;
  1941.     board->intgp.k=0;
  1942.  
  1943.     memset(board->sqused,0xff,(BOARDX+1)*(BOARDY+2)*sizeof(short));
  1944.  
  1945.     for(i=0;i<GROUPS;i++)
  1946.         {
  1947.         if(threat_group(board,i,BLACK))
  1948.             {
  1949.             board->intgp.tgroups[i]=YES;
  1950.             board->intgp.j++;
  1951.             }
  1952.         else board->intgp.tgroups[i]=NO;
  1953.  
  1954.         if(threat_group(board,i,WHITE))
  1955.             {
  1956.             board->intgp.mygroups[i]=YES;
  1957.             board->intgp.k++;
  1958.             }
  1959.         else board->intgp.mygroups[i]=NO;
  1960.         }
  1961.  
  1962.     fprintf(h1,"There are %d groups in which red can connect four men and ",board->intgp.j);
  1963.     fprintf(h1,"%d dangerous\ngroups in which yellow can connect four men.\n",board->intgp.k);
  1964.     fprintf(h1,"\n");
  1965.  
  1966.     claimeven(board);
  1967.     baseinverse(board);
  1968.     vertical(board);
  1969.     aftereven(board);
  1970.     lowinverse(board);
  1971.     highinverse(board);
  1972.     baseclaim(board);
  1973.     before(board);
  1974.  
  1975.     if(board->intgp.j==0)
  1976.         {
  1977.         fprintf(h1,"This implies that at least a draw is guaranteed.\n");
  1978.  
  1979.         oracle=YES;
  1980.         goto BSS_ENDING;
  1981.         }
  1982.  
  1983.     if(board->sp==0)
  1984.         {
  1985.         fprintf(h1,"No rules can be applied to solve the aforementioned groups in which\n");
  1986.         fprintf(h1,"yellow can connect four men. Therefore nothing can be said about red.\n");
  1987.  
  1988.         oracle=NO;
  1989.         goto BSS_ENDING;
  1990.         }
  1991.  
  1992.     fprintf(h1,"Total number of rule instances is: %d\n\n",board->sp);
  1993.  
  1994.     matrix=(char **)allocate_matrix(board);
  1995.     build_adjacency_matrix(matrix,board);
  1996.  
  1997.     oracle=problem_solver(board,matrix,YES,h1);
  1998.     free_matrix(matrix,board);
  1999.  
  2000.     BSS_ENDING:
  2001.  
  2002.     fprintf(h1,"\n");
  2003.     fclose(h1);
  2004.     return oracle;
  2005.     }
  2006.  
  2007.  
  2008. short ss_evaluate_white(struct board *board)
  2009.     {
  2010.     FILE *h1;
  2011.     short x,y;
  2012.     struct threat_combo tc[GROUPS];
  2013.     short threats[MAXGROUPS],thnum=0,combo,ccmb;
  2014.     short key,oracle,anythreat=0;
  2015.     char **matrix;
  2016.     short i,*bpos,px,py;
  2017.  
  2018.     h1=fopen(TMPFILENAME,"w");
  2019.     if(!h1) fatal_error("Cannot open temporary file");
  2020.  
  2021.     fprintf(h1,"Oracle analysis for yellow:\n\n");
  2022.  
  2023.     combo=threat_combo(board,tc);
  2024.     thnum=count_odd_threats(board,threats);
  2025.     if(thnum+combo==0)
  2026.         {
  2027.         fprintf(h1,"There are no single or double threats for yellow\n");
  2028.         fprintf(h1,"therefore nothing can be said about yellow possibilities\n");
  2029.  
  2030.         oracle=NO;
  2031.         goto WSS_ENDING;
  2032.         }
  2033.  
  2034.     fprintf(h1,"There are %d odd threats and %d double threats for yellow\n\n",
  2035.             thnum,combo);
  2036.  
  2037.     do
  2038.         {
  2039.         for(x=0;x<75;x++)
  2040.             fputc('*',h1);
  2041.  
  2042.         fprintf(h1,"\n\nCase #%d: ",anythreat+1);
  2043.  
  2044.         memset(board->usablegroup,0xff,GROUPS*sizeof(short));
  2045.         memset(board->sqused,0xff,(BOARDX+1)*(BOARDY+2)*sizeof(short));
  2046.         memset(board->wipesq,0x00,(BOARDX+1)*(BOARDY+2)*sizeof(short));
  2047.  
  2048.         if(anythreat<thnum)
  2049.             {
  2050.             fprintf(h1,"odd threat at %c%d.\n\n",
  2051.                     ELX(threats[anythreat])+'a',ELY(threats[anythreat])+1);
  2052.  
  2053.             wipe_above(board,threats[anythreat]);
  2054.             wipe_odd(board,threats[anythreat]);
  2055.  
  2056.             px=ELX(threats[anythreat]);
  2057.             for(py=0;py<BOARDY;py++)
  2058.                 if(board->square[ELM(px,py)]==EMPTY)
  2059.                     board->sqused[ELM(px,py)]=NO;
  2060.             }
  2061.         else
  2062.             {
  2063.             ccmb=anythreat-thnum;
  2064.  
  2065.             px=ELX(tc[ccmb].cross);
  2066.             x =ELX(tc[ccmb].odd);
  2067.  
  2068.             fprintf(h1,"double threat at %c%d.\n\n",
  2069.                     ELX(tc[ccmb].cross)+'a',ELY(tc[ccmb].cross)+1);
  2070.  
  2071.             for(y=0;y<BOARDY;y++)
  2072.                 {
  2073.                 if(board->square[ELM(px,y)]==EMPTY)
  2074.                     board->sqused[ELM(px,y)]=NO;
  2075.  
  2076.                 if(board->square[ELM( x,y)]==EMPTY)
  2077.                     board->sqused[ELM( x,y)]=NO;
  2078.                 }
  2079.  
  2080.             if(ELY(tc[ccmb].even)>ELY(tc[ccmb].odd))
  2081.                 handle_even_above_odd(board,&tc[ccmb]);
  2082.             else
  2083.                 handle_odd_above_even(board,&tc[ccmb]);
  2084.             }
  2085.  
  2086.         board->sp=0;
  2087.         board->intgp.j=0;
  2088.         board->intgp.k=0;
  2089.  
  2090.         fprintf(h1,"Eliminating squares: ");
  2091.  
  2092.         for(x=0;x<BOARDX;x++)
  2093.             for(y=0;y<BOARDY;y++)
  2094.                 if(!board->sqused[ELM(x,y)])
  2095.                     fprintf(h1,"%c%d ",x+'a',y+1);
  2096.  
  2097.         fprintf(h1,"\n\n");
  2098.  
  2099.         for(i=0;i<GROUPS;i++)
  2100.             {
  2101.             if(threat_group(board,i,WHITE) &&
  2102.                 !wiped_group(board,i) && board->usablegroup[i])
  2103.                 {
  2104.                 board->intgp.tgroups[i]=YES;
  2105.                 board->intgp.j++;
  2106.                 }
  2107.             else board->intgp.tgroups[i]=NO;
  2108.  
  2109.             if(threat_group(board,i,BLACK))
  2110.                 {
  2111.                 board->intgp.mygroups[i]=YES;
  2112.                 board->intgp.k++;
  2113.             }
  2114.             else board->intgp.mygroups[i]=NO;
  2115.             }
  2116.  
  2117.         for(y=0;y<BOARDY;y++)
  2118.             for(x=0;x<BOARDX;x++)
  2119.                 if(board->square[ELM(x,y)]!=EMPTY &&
  2120.                    board->sqused[ELM(x,y)]==NO)
  2121.                       fatal_error("Marked as used an useless square...");
  2122.  
  2123.         fprintf(h1,"There are %d group(s) in which yellow can connect four men and ",board->intgp.j);
  2124.         fprintf(h1,"%d dangerous\ngroup(s) in which red can connect four men.\n",board->intgp.k);
  2125.         fprintf(h1,"\n");
  2126.  
  2127.         claimeven(board);
  2128.         baseinverse(board);
  2129.         vertical(board);
  2130.         aftereven(board);
  2131.         lowinverse(board);
  2132.         highinverse(board);
  2133.         baseclaim(board);
  2134.         before(board);
  2135.  
  2136.         if(board->intgp.j==0)
  2137.             {
  2138.             fprintf(h1,"This implies that a win is guaranteed.\n");
  2139.             oracle=YES;
  2140.             }
  2141.  
  2142.         else if(board->sp==0)
  2143.             {
  2144.             fprintf(h1,"No rules can be applied to solve the aforementioned groups in which\n");
  2145.             fprintf(h1,"red can connect four men. Therefore nothing can be said about yellow.\n");
  2146.             oracle=NO;
  2147.             }
  2148.  
  2149.         else
  2150.             {
  2151.             fprintf(h1,"Total number of rule instances is: %d\n\n",board->sp);
  2152.  
  2153.             matrix=(char **)allocate_matrix(board);
  2154.             build_adjacency_matrix(matrix,board);
  2155.  
  2156.             oracle=problem_solver(board,matrix,YES,h1);
  2157.             free_matrix(matrix,board);
  2158.             }
  2159.  
  2160.         fprintf(h1,"\n");
  2161.  
  2162.         anythreat++;
  2163.         } while(anythreat<thnum+combo && oracle==NO);
  2164.  
  2165.     if(oracle==YES && anythreat<thnum+combo)
  2166.         {
  2167.         fprintf(h1,"No further cases are taken into consideration since\n");
  2168.         fprintf(h1,"this last case is sufficient to prove yellow can win\n");
  2169.         fprintf(h1,"from this position.\n");
  2170.         }
  2171.  
  2172.     WSS_ENDING:
  2173.  
  2174.     fprintf(h1,"\n");
  2175.     fclose(h1);
  2176.     return oracle;
  2177.     }
  2178.  
  2179. short ss_evaluation_function(struct board *board)
  2180.     {
  2181.     switch(board->turn)
  2182.         {
  2183.         case WHITE:
  2184.             return ss_evaluate_black(board);
  2185.  
  2186.         case BLACK:
  2187.             return ss_evaluate_white(board);
  2188.         }
  2189.  
  2190.     return NOCOMMENT;
  2191.     }
  2192.